home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
keyb
/
visitype.zip
/
VISITYPE.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-10-11
|
10KB
|
436 lines
vectors segment at 0H ; set up segment to intercept Interrupts
org 9H*4 ; the keyboard Interrupt
keyboard_int label word
org 1CH*4 ; timer interrupt
timer_vector label word
vectors ends
screen segment at 0B000H ; a dummy segment to use as the
screen ends ; extra segment
rom_bios_data segment at 40H ; bios statuses held here, also keyboard buffer
org 1AH
head dw ? ; unread chars go from head to tail
tail dw ?
buffer dw 16 dup (?) ; the buffer itself
buffer_end label word
rom_bios_data ends
code_seg segment
assume cs:code_seg
org 100H ; org = 100H to make this into a .COM file
first: jmp load_buffer ; first time through
copy_right db 'Copyright 1986 Ziff-Davis Publishing Co.'
buff dw 0
buff2 dw 159 dup(0)
pad_offset dw 0 ; chooses 1st 160 bytes or 2nd
screen_seg_offset dw 0 ; 0 for mono, 8000H for graphics
io_char dw 1 ; holds addr of put or get_char
old_head dw 1 ; to check for typeahead
display_on db 0 ; 0 -> off
status_port dw 0 ; video controller status port
near_attrib_flag db 0 ; used in put_char
old_keyboard_int_label label dword
old_keyboard_int dw 0 ; location of old kbd interrupt
dw 0
rom_timer_label label dword
rom_timer dw 0 ; the timer interrupt's address
dw 0
bufstuff proc near ; the keyboard interrupt will now come here
assume cs:code_seg
push ax ; save the used registers for good form
push bx
push cx
push dx
push di
push si
push ds
push es
pushf ; first, call old keyboard interrupt
call old_keyboard_int_label
assume ds:rom_bios_data ; examine the char just put in
mov bx,rom_bios_data
mov ds,bx
mov bx,tail ; point to current tail
cmp bx,head ; if at head, kbd int has deleted char
jne cont
jmp out ; so leave
cont:
mov dx,tail ; read a char - head advances
sub dx,2 ; point to just read in character
cmp dx,offset buffer ; did we undershoot buffer?
jae nowrap ; nope
mov dx,offset buffer_end ; yes - move to buffer top
sub dx,2
nowrap:
mov bx,dx
mov cx,[bx] ; get key in cx
cmp cx,buff ; is it where we were before?
jne t10
mov bx,head ; has the head moved?
cmp bx,old_head
je t11 ; if yes, we have moved
t10:
cmp buff2,0
jne remove ; if there's something in buff2,
t11:
cmp dx,head ; remove char in kbd buffer
jne remove
jmp out ; do nothing this pass
; more than one char in buffer - remove one
remove:
mov bx,dx
mov tail,dx ; remove character by adjusting tail
mov dx,[bx] ; store character in buffer
mov cx,80
mov bx,0 ; find end of visitype buffer
check:
cmp buff2[bx],0
je bufend
add bx,2
loop check
cmp dx,0E08H ; was this key a rubout?
jne out ; no, and buffer filled - leave
mov bx,158 ; yes, buff full but rubout last char
mov word ptr buff[bx],0
mov bx,head
mov old_head,bx ; store this for next time
mov dx,[bx] ; always load buff
mov buff,dx
jmp out ; can't hold more than 80
bufend:
cmp dx,0E08H ; rubout (and buffer not full)?
jne nodel ; no, don't del
del:
sub bx,2 ; yes, delete last key
cmp bx,0FFFEH ; gone too far?
jl out
jne paddel
mov cx,tail ; del the one char in kdb buffer
mov head,cx ; by making tail = head
mov buff,0
jmp short chkdis
paddel:
mov dx,0 ; dx -> 0 if we are deleting
nodel:
mov buff2[bx],dx ; load key in visitype buffer
mov bx,head
mov old_head,bx ; and store the old head to check later
mov dx,[bx] ; always reload buff
mov buff,dx
chkdis:
cmp display_on,0 ; are we on?
jne flash ; yes, call display
mov display_on,0FFH ; store what's on the screen first
mov pad_offset,160
lea ax,get_char ; make io use get-char so it does
mov io_char,ax
call io ; get top line from screen
flash:
call display ; display visitype's top line
out:
pop es ; having done pushes, here are the pops
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
iret ; an interrupt needs an iret
bufstuff endp
display proc near ; puts the whole pad on the screen
push ax
mov near_attrib_flag,0
mov pad_offset,0 ; use 1st bytes of pad memory
lea ax,put_char ; make io use put-char so it does
mov io_char,ax
call io ; put result on screen
pop ax
ret ; leave
display endp
get_char proc near ; gets a char from screen and advances position
assume es:screen,ds:rom_bios_data
push dx
mov si,2 ; loop twice, once for char, once for attribute
mov dx,status_port ; get ready to read video controller status
g_wait_low: ; start waiting for a new horizontal scan -
in al,dx ; make sure the video controller scan status
test al,1 ; is low
jnz g_wait_low
g_wait_high: ; after port has gone low, it must go high
in al,dx ; before it is safe to read directly from
test al,1 ; the screen buffer in memory
jz g_wait_high
mov ax,es:[di] ; do the move from the screen, one byte at a time
inc di ; move to next screen location
dec si ; decrement loop counter
cmp si,0 ; are we done?
je leave ; yes
mov buff[bx],ax ; no - put char we got into buff
jmp g_wait_low ; do it again
leave:
add bx,2
pop dx
ret
get_char endp
put_char proc near ; puts one char on screen and advances position
push dx
cli
mov ah,byte ptr buff[bx]
mov si,2 ; loop twice, once for char, once for attribute
mov dx,status_port ; get ready to read video controller status
p_wait_low: ; start waiting for a new horizontal scan -
in al,dx ; make sure the video controller scan status
test al,1 ; is low
jnz p_wait_low
p_wait_high: ; after port has gone low, it must go high
in al,dx ; before it is safe to write directly to
test al,1 ; the screen buffer in memory
jz p_wait_high
mov es:[di],ah ; move to screen, one byte at a time
mov ah,byte ptr buff[bx+1]
cmp near_attrib_flag,0
jne incdi
mov ah,byte ptr buff[bx+161]
incdi:
inc di ; point to next screen postion
dec si ; decrement loop counter
jnz p_wait_low ; if not zero, do it one more time
add bx,2
pop dx
sti
ret ; exeunt
put_char endp
io proc near ; this scans over screen positions on top line
assume es:screen ; use screen as extra segment
mov bx,screen
mov es,bx
mov di,screen_seg_offset ; di will be pointer to screen postion
mov bx,pad_offset ; bx will be location pointer
mov cx,80
char_loop:
call io_char ; call put-char or get-char
loop char_loop ; if not zero, scan over next character
ret ; finished
io endp
assume ds:code_seg
intercept_timer proc near ; this completes filling the buffer
; if no keys in buffer, put next one in
push ds ; save DS since we'll change it
push cs ; put current value of CS into DS
pop ds
pushf
call rom_timer_label ; make obligatory call
cmp buff2,0
jne go ; no, leave
jmp out1
go:
cli ; yes, start by clearing interrupts
push es
push ds ; save these
push si
push di
push dx
push cx
push bx
push ax
assume ds:rom_bios_data ; point to the keyboard buffer again
mov ax,rom_bios_data
mov ds,ax
mov bx,tail ; prepare to put characters in at tail
cmp head,bx ; if kbd buff not empty, leave
jne finstuff
stuff:
mov ax,word ptr buff2 ; get the char to put in kbd buffer
mov cx,79 ; now slide the rest over
mov bx,0
slide:
mov dx,buff[bx+2] ; do this word by word
mov buff[bx],dx
add bx,2
inc si
loop slide ; slides slides buff to the left
mov word ptr buff2[bx-2],0
mov dx,head ; store this to check if user is typing
mov old_head,dx ; while we drain buff
mov dx,tail ; find position in buffer from bx
add dx,2 ; move to next position for this word
cmp dx,offset buffer_end ; are we past the end?
jl no_wrap ; no, don't wrap
mov dx,offset buffer ; do the wrap rap
no_wrap:
cmp dx,head ; buffer full but not yet done?
je finstuff ; time to leave, come back later
mov bx,tail ; prepare to put characters in at tail
mov [bx],ax ; put into buffer
mov